package com.devops.controller;

import com.devops.dto.ApiResponse;
import com.devops.mapper.UserMapper;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/test")
@CrossOrigin(origins = "*")
public class TestController {

    private static final String USER_COUNT_CACHE_KEY = "cache:users:count";
    private static final long USER_COUNT_TTL_SECONDS = 30L;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisProperties redisProperties;

    @Autowired
    private UserMapper userMapper;

    /**
     * 缓存演示：优先从 Redis 获取用户总数，未命中则查询数据库并写入缓存
     */
    @GetMapping("/redis")
    public ResponseEntity<ApiResponse<Map<String, Object>>> testRedisCache() {
        long start = System.nanoTime();
        Map<String, Object> data = new HashMap<>();
        String source;
        String valueStr = null;
        Long ttlLeft = null;

        try {
            valueStr = stringRedisTemplate.opsForValue().get(USER_COUNT_CACHE_KEY);
            if (valueStr != null) {
                source = "redis";
                ttlLeft = stringRedisTemplate.getExpire(USER_COUNT_CACHE_KEY, TimeUnit.SECONDS);
            } else {
                // miss: query DB
                int count = userMapper.countUsers();
                valueStr = String.valueOf(count);
                source = "db";
                stringRedisTemplate.opsForValue().set(
                        USER_COUNT_CACHE_KEY,
                        valueStr,
                        Duration.ofSeconds(USER_COUNT_TTL_SECONDS)
                );
                ttlLeft = USER_COUNT_TTL_SECONDS;
            }

            long durationMs = (System.nanoTime() - start) / 1_000_000;
            data.put("metric", "users.count");
            data.put("value", Integer.parseInt(valueStr));
            data.put("source", source);
            data.put("durationMs", durationMs);
            data.put("ttlSeconds", ttlLeft);
            return ResponseEntity.ok(ApiResponse.success("缓存演示成功", data));
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("Redis/数据库访问失败: " + rootCause(e)));
        }
    }

    /**
     * 直接从数据库查询用户总数（不走缓存），用于对比
     */
    @GetMapping("/mysql")
    public ResponseEntity<ApiResponse<Map<String, Object>>> testMySqlDirect() {
        long start = System.nanoTime();
        Map<String, Object> data = new HashMap<>();
        try {
            int count = userMapper.countUsers();
            long durationMs = (System.nanoTime() - start) / 1_000_000;
            data.put("metric", "users.count");
            data.put("value", count);
            data.put("source", "db");
            data.put("durationMs", durationMs);
            return ResponseEntity.ok(ApiResponse.success("数据库查询成功", data));
        } catch (Exception e) {
            return ResponseEntity.ok(ApiResponse.error("数据库访问失败: " + rootCause(e)));
        }
    }

    /**
     * 模拟 Elasticsearch 测试，返回静态信息，方便前端演示
     */
    @GetMapping("/elasticsearch")
    public ResponseEntity<ApiResponse<Map<String, Object>>> testElasticsearchMock() {
        Map<String, Object> data = new HashMap<>();
        data.put("clusterName", "mock-es");
        data.put("status", "green");
        data.put("version", "8.x-mock");
        return ResponseEntity.ok(ApiResponse.success("Elasticsearch 模拟成功", data));
    }

    /**
     * 直接 PING Redis，并返回连接参数，便于排查
     */
    @GetMapping("/redis/ping")
    public ResponseEntity<ApiResponse<Map<String, Object>>> pingRedis() {
        Map<String, Object> data = new HashMap<>();
        data.put("host", redisProperties.getHost());
        data.put("port", redisProperties.getPort());
        data.put("database", redisProperties.getDatabase());
        data.put("username", redisProperties.getUsername());
        data.put("hasPassword", redisProperties.getPassword() != null);
        try {
            String pong = stringRedisTemplate.getConnectionFactory().getConnection().ping();
            data.put("ping", pong);
            return ResponseEntity.ok(ApiResponse.success("Redis 连接正常", data));
        } catch (Exception e) {
            data.put("error", rootCause(e));
            return ResponseEntity.ok(ApiResponse.error("Redis 连接失败: " + rootCause(e)));
        }
    }

    private String rootCause(Throwable t) {
        Throwable cur = t;
        while (cur.getCause() != null) cur = cur.getCause();
        return cur.getMessage() != null ? cur.getMessage() : t.toString();
    }

    /**
     * 回显当前运行时 Redis 配置（不返回明文密码）
     */
    @GetMapping("/redis/config")
    public ResponseEntity<ApiResponse<Map<String, Object>>> echoRedisConfig() {
        Map<String, Object> data = new HashMap<>();
        data.put("host", redisProperties.getHost());
        data.put("port", redisProperties.getPort());
        data.put("database", redisProperties.getDatabase());
        data.put("username", redisProperties.getUsername());
        data.put("hasPassword", redisProperties.getPassword() != null && !redisProperties.getPassword().isEmpty());
        return ResponseEntity.ok(ApiResponse.success("Redis 配置读取成功", data));
    }
}
